#pragma once
#include <vector>
#include "Singleton.h"
#include "CSV.h"

#define PROFILER_DISABLE

#ifdef PROFILER_ENABLE
#define TIME_AUTO(x) auto_struct s(x);
#else
#define TIME_AUTO(x)
#endif

typedef unsigned long long largeint;

struct auto_struct
{
	auto_struct(const char* n);
	~auto_struct();

	largeint startTime;
	largeint endTime;
};

struct PerformanceData
{
	PerformanceData(const char* n)
	{
		assert(n);
		name = n;
		nCalls = 1; // only created when called, so it is at least 1
		totalTime = 0;
	}

	const char* name;
	int nCalls;
	largeint totalTime;
};

class ProfilerNode
{
public:
	ProfilerNode() { isNested = 0; parent = 0; }
	void addChild(ProfilerNode* n) { children.push_back(n); }

	int isNested;
	ProfilerNode* parent;
	std::vector<ProfilerNode*> children;
	PerformanceData* data;
};

class Profiler
	: public Singleton<Profiler>
{
public:
	Profiler(void);
	~Profiler(void);

	void startProfiler() {  }

	void functionStart(const char* n);
	void functionEnd(largeint& espladedTime);

	static inline void getTime(largeint& i);
	void dump() const;
private:
	inline float getMsTime(const largeint& i) const;
	float dumpNode(const ProfilerNode* node,CSV& file,std::string& format) const;
	float dumpNodeAfter(const ProfilerNode* node,CSV& file,int& row,float totalTime) const;

	void writeContent(CSV& file,const std::string& format,const std::string& name, int calls, float totalms) const;
	void writePercentage(CSV& file,float percent) const;
private:
	ProfilerNode *root,*currentNode;
	int childIndex;
	size_t stackPointer;
};